home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-01 / ue312src.zip / MSWEMACS.C < prev    next >
C/C++ Source or Header  |  1993-04-21  |  16KB  |  503 lines

  1. /* The routines in this file provide extra emacs functions available
  2.    under the Microsoft Windows environment on an IBM-PC or compatible
  3.    computer. The following functions are supplied: cutregion,
  4.    clipregion, insertclip and helpengine.
  5.    Also implemented here is the support for scroll bars
  6.  
  7.    Must be compiled with Borland C++ 2.0 or MSC 6.0 or later versions
  8.  
  9.    It should not be compiled if the WINDOW_MSWIN symbol is not set */
  10.  
  11. #include    "estruct.h"
  12. #include    <stdio.h>
  13. #include    "eproto.h"
  14. #include    "edef.h"
  15. #include    "elang.h"
  16.  
  17. #include    "mswin.h"
  18.  
  19. #include    "mswmenu.h"
  20. /* to invoke the commands corresponding to scroll bar actions */
  21.  
  22. #define MAXSCROLL 32767 /* maximum position for scrollbars */
  23.  
  24. static HANDLE   hClipData = NULL;   /* used by insertclip and
  25.                        ClipboardCleanup */
  26.  
  27. /* CopyToClipboard: internal function to copy region to clipboard */
  28. /* ===============                                                */
  29.  
  30. static BOOL PASCAL CopyToClipboard (REGION *Region)
  31. {
  32.     long    Size = 0L;
  33.     HANDLE  hData;
  34. #if WINDOW_MSWIN32
  35.     char    *Data;
  36. #else
  37.     char huge *Data;
  38. #endif
  39.     BOOL    Result = TRUE;
  40.     register LINE *lp;
  41.     register int Offset;
  42.     register int lcnt;       /* used to reduce longop() overhead */
  43.     
  44.     /*-figure out the size of the clipboard data (end of lines have to
  45.        be turned into CR-LF) */
  46.     Size = Region->r_size;
  47.     if (curwp->w_dotp != curwp->w_markp[0]) {   /* multiple lines */
  48.         lp = Region->r_linep;
  49.         do {
  50.             ++Size;
  51.         lp = lforw(lp);
  52.     } while ((lp != curwp->w_dotp) && (lp != curwp->w_markp[0]));
  53.     }
  54.     if (Size == 0L) return TRUE;
  55.  
  56.     /*-copy the buffer data into a block of global memory */
  57.     if (hData = GlobalAlloc (GMEM_MOVEABLE, Size + 1)) {
  58.         if (!(Data = GlobalLock (hData))) goto NoClipboardMemory;
  59.     lp = Region->r_linep;
  60.     Offset = Region->r_offset;
  61.     lcnt = 0;
  62.     while (Size-- > 0) {
  63.         if (Offset != lused(lp)) {    /* middle of line */
  64.             *Data++ = lgetc(lp, Offset);
  65.             ++Offset;
  66.         }
  67.         else {                          /* end of line */
  68.             *Data++ = '\r';
  69.             *Data++ = '\n';
  70.             Size--;
  71.             lp = lforw(lp);
  72.             Offset = 0;
  73.             if (--lcnt < 0) {
  74.             longop (TRUE);
  75.             lcnt = 10;  /* reduce longop calls overhead */
  76.         }
  77.         }
  78.     }
  79.     *Data = '\0';
  80.     /*-pass the text to the clipboard */
  81.     GlobalUnlock (hData);
  82.     if (OpenClipboard (hFrameWnd)) {
  83.         if (EmptyClipboard ()) {
  84.             SetClipboardData (CF_TEXT, hData);
  85.         }
  86.         else Result = FALSE;
  87.         CloseClipboard ();
  88.     }
  89.     else Result = FALSE;
  90.     if (Result == FALSE) GlobalFree (hData);
  91.     }
  92.     else {
  93. NoClipboardMemory:
  94.     mlabort (TEXT94);   /* out of memory */
  95.         Result = FALSE;
  96.     }
  97.     return Result;
  98. } /* CopyToClipboard */
  99.  
  100. /* cutregion:   move the current region to the clipboard */
  101. /* =========                                             */
  102.  
  103. PASCAL cutregion (int f, int n)
  104. {
  105.     REGION  Region;
  106.     int     Result;
  107.  
  108.     /*-don't allow command if read-only mode */
  109.     if (curbp->b_mode & MDVIEW) return rdonly();
  110.  
  111.     if ((Result = getregion (&Region)) != TRUE) return Result;
  112.  
  113.     if ((Result = CopyToClipboard (&Region)) != TRUE) return Result;
  114.     curwp->w_dotp = Region.r_linep;
  115.     curwp->w_doto = Region.r_offset;
  116.     return ldelete (Region.r_size, FALSE);
  117. } /* cutregion */
  118.  
  119. /* clipregion:  copy the current region into the clipboard */
  120. /* ==========                                              */
  121.  
  122. PASCAL clipregion (int f, int n)
  123. {
  124.     REGION  Region;
  125.     int     Result;
  126.     
  127.     if ((Result = getregion (&Region)) != TRUE) return Result;
  128.  
  129.     return CopyToClipboard (&Region);
  130. } /* clipregion */
  131.  
  132. /* insertclip:  insert the clipboard contents at dot */
  133. /* ==========                                        */
  134.  
  135. PASCAL insertclip (int f, int n)
  136. {
  137.     BOOL    Result = TRUE;
  138.     char    *Text, *TextHead;
  139.     short int curoff;
  140.     LINE    *curline;
  141.  
  142.     /*-don't allow command if read-only mode */
  143.     if (curbp->b_mode & MDVIEW) return rdonly();
  144.  
  145.     if (OpenClipboard (hFrameWnd)) {
  146.     if ((hClipData = GetClipboardData (CF_TEXT)) != NULL) {
  147.         /* Save the local pointers to hold global "." */
  148.         if (yankflag == SRBEGIN) {
  149.         /* Find the *previous* line, since the line we are on
  150.            may disappear due to re-allocation.  This works even
  151.            if we are on the first line of the file. */
  152.         curline = lback(curwp->w_dotp);
  153.         curoff = curwp->w_doto;
  154.         }
  155.         if ((TextHead = GlobalLock (hClipData)) != NULL) {
  156.         while (n--) {
  157.             Text = TextHead;
  158.             while (*Text != '\0') {
  159.             if (*Text == '\n') {
  160.                 if (lnewline () == FALSE) {
  161.                 Result = FALSE;
  162.                 goto bail_out;
  163.                 }
  164.             }
  165.             else {
  166.                 if (*Text != '\r') if (linsert (1, *Text) == FALSE) {
  167.                 Result = FALSE;
  168.                 goto bail_out;
  169.                 }
  170.             }
  171.             ++Text;
  172.             }
  173.         }
  174. bail_out:
  175.                 GlobalUnlock (hClipData);
  176.                 hClipData = NULL;   /* for ClipboardCleanup */
  177.                 /* If requested, set global "." back to the beginning of
  178.            the yanked text. */
  179.         if (yankflag == SRBEGIN) {
  180.             curwp->w_dotp = lforw(curline);
  181.             curwp->w_doto = curoff;
  182.         }
  183.         }
  184.     }
  185.     else Result = FALSE;
  186.     CloseClipboard ();
  187.     }
  188.     else Result = FALSE;
  189.     return Result;
  190. } /* insertclip */
  191.  
  192. /* ClipboardCleanup:    to be called if the user aborts during a longop */
  193. /* ================                                                     */
  194.  
  195. void FAR PASCAL ClipboardCleanup (void)
  196. {
  197.     if (hClipData) {
  198.         GlobalUnlock (hClipData);
  199.         CloseClipboard ();
  200.     }
  201. } /* ClipboardCleanup */
  202.  
  203. /* helpengine:  invoke the MS-Windows help engine */
  204. /* ==========                                     */
  205.  
  206. PASCAL helpengine (int f, int n)
  207. {
  208.     char    OldHelpFile [NFILEN];
  209.     char    HelpKey [NLINE];
  210.     BOOL    Result;
  211.  
  212.     strcpy (OldHelpFile, HelpEngineFile);
  213.     SetWorkingDir ();
  214.     if ((Result = FILENAMEREPLY (TEXT307, HelpEngineFile, NFILEN)) != TRUE) return Result;
  215.         /* "Help file: " */
  216.     if (HelpEngineFile[0] == '\0') {
  217.         strcpy (HelpEngineFile, OldHelpFile);
  218.         return FALSE;
  219.     }
  220.     else {
  221.         Result = mlreply (TEXT308, HelpKey, NLINE);
  222.     if ((Result != TRUE) && (Result != FALSE)) return Result;
  223.         /* "Help key: " */
  224.     if (HelpKey[0] == '\0') {
  225.         WinHelp (hFrameWnd, HelpEngineFile, HELP_INDEX, NULL);
  226.     }
  227.     else {
  228.         WinHelp (hFrameWnd, HelpEngineFile, HELP_KEY,
  229.                      (DWORD)(LPSTR)&HelpKey[0]);
  230.     }
  231.     }
  232.     return TRUE;
  233. } /* helpengine */
  234.  
  235. /* minimizescreen:  turn the current screen into an icon */
  236. /* ==============                                        */
  237.  
  238. PASCAL  minimizescreen (int f, int n)
  239. {
  240.     BOOL    nq;
  241.  
  242.     nq = notquiescent;
  243.     notquiescent = 0;
  244.     ShowWindow (first_screen->s_drvhandle, SW_MINIMIZE);
  245.     notquiescent = nq;
  246.     return TRUE;
  247. } /* minimizescreen */
  248.  
  249. /* ForceMessage:    do a SendMessage, forcing quiescent mode */
  250. /* ============                                              */
  251.  
  252. static PASCAL ForceMessage (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  253. {
  254.     BOOL    nq;
  255.  
  256.     nq = notquiescent;
  257.     notquiescent = 0;
  258.     SendMessage (hWnd, wMsg, wParam, lParam);
  259.     notquiescent = nq;
  260. } /* ForceMessage */
  261.  
  262. /* maximizescreen:  maximize the current screen */
  263. /* ==============                               */
  264.  
  265. PASCAL  maximizescreen (int f, int n)
  266. {
  267.     ForceMessage (hMDIClientWnd, WM_MDIMAXIMIZE,
  268.                   (UINT)first_screen->s_drvhandle, 0L);
  269.     return TRUE;
  270. } /* maximizescreen */
  271.  
  272. /* restorescreen:   restore the current screen from maximized/minimized state */
  273. /* =============                                                              */
  274.  
  275. PASCAL  restorescreen (int f, int n)
  276. {
  277.     ForceMessage (hMDIClientWnd, WM_MDIRESTORE,
  278.                   (UINT)first_screen->s_drvhandle, 0L);
  279.     return TRUE;
  280. } /* restorescreen */
  281.  
  282. /* tilescreens: tile the non-iconized screens */
  283. /* ===========                                */
  284.  
  285. PASCAL  tilescreens (int f, int n)
  286.  
  287. /* without a numeric argument, tile horizontally. With a numeric argument
  288.    of 1, tile vertically */
  289. {
  290.     if (f && (n == 1)) {
  291.         ForceMessage (hMDIClientWnd, WM_MDITILE, MDITILE_HORIZONTAL, 0L);
  292.     }
  293.     else ForceMessage (hMDIClientWnd, WM_MDITILE, MDITILE_VERTICAL, 0L);
  294.     return TRUE;
  295. } /* tilescreens */
  296.  
  297. /* cascadescreens:  position the non-iconized screens in cascade */
  298. /* ==============                                                */
  299.  
  300. PASCAL  cascadescreens (int f, int n)
  301. {
  302.     ForceMessage (hMDIClientWnd, WM_MDICASCADE, 0, 0L);
  303.     return TRUE;
  304. } /* cascadescreens */
  305.  
  306. /* ScrollMessage:   handle WM_HSCROLL and WM_VSCROLL */
  307. /* =============                                     */
  308. void FAR PASCAL ScrollMessage (HWND hWnd, UINT wMsg, WORD ScrlCode, int Pos)
  309.  
  310. {
  311.     int     Delta;
  312.     
  313.     if (notquiescent) return;
  314.     
  315.     if (wMsg == WM_VSCROLL) {
  316.         switch (ScrlCode) {
  317.             case SB_LINEUP:
  318.                 mvupwind (FALSE, 1);
  319.                 break;
  320.             case SB_LINEDOWN:
  321.                 mvdnwind (FALSE, 1);
  322.                 break;
  323.             case SB_PAGEUP:
  324.                 backpage (FALSE, 1);
  325.                 break;
  326.             case SB_PAGEDOWN:
  327.                 forwpage (FALSE, 1);
  328.                 break;
  329.             case SB_THUMBTRACK:
  330.             case SB_THUMBPOSITION:
  331.                 if (Win31API) {
  332.                     if (ScrlCode == SB_THUMBPOSITION) return;
  333.                 }
  334.                 else {
  335.                     if (ScrlCode == SB_THUMBTRACK) return;
  336.                     /* there is something wrong with thumb tracking in
  337.                        Windows 3.0 */
  338.                 }
  339.                 Delta = Pos - GetScrollPos (hWnd, SB_VERT);
  340.                 if (Delta) mvdnwind (TRUE, Delta);
  341.                 break;
  342.             default:
  343.                 return;
  344.         }
  345.         curwp->w_flag |= WFMODE;
  346.     }
  347.     else {
  348.         switch (ScrlCode) {
  349.             case SB_LINEUP:
  350.                 Delta = -1;
  351.                 break;
  352.             case SB_LINEDOWN:
  353.                 Delta = 1;
  354.                 break;
  355.             case SB_PAGEUP:
  356.                 Delta = -term.t_ncol;
  357.                 break;
  358.             case SB_PAGEDOWN:
  359.                 Delta = term.t_ncol;
  360.                 break;
  361.             case SB_THUMBTRACK:
  362.                 Delta = Pos - GetScrollPos (hWnd, SB_HORZ);
  363.                 break;
  364.             default:
  365.                 return;
  366.         }
  367.         curwp->w_fcol += Delta;
  368.         if (curwp->w_fcol < 0) curwp->w_fcol = 0;
  369.         if (curwp->w_doto < curwp->w_fcol) {
  370.             /* reframe dot if it was left past the left of the screen */
  371.             curwp->w_doto = min(curwp->w_fcol,lused(curwp->w_dotp));
  372.         }
  373.         if (curwp->w_doto > (curwp->w_fcol + term.t_ncol - 2)) {
  374.             /* reframe dot if it was left past the right of the screen */
  375.             curwp->w_doto = curwp->w_fcol + term.t_ncol - 2;
  376.     }
  377.         curwp->w_flag |= WFMODE | WFHARD;
  378.     }
  379.     if (in_check()) GenerateMenuSeq (IDM_NULLPROC);
  380.         /* this ensures we go through the editloop(), updating the
  381.            modeline display and running the cmdhook, among other things */
  382.     ShowEmacsCaret (FALSE);
  383.     update (TRUE);
  384.     ShowEmacsCaret (TRUE);
  385. } /* ScrollMessage */
  386.  
  387. /* ScrollBars:      shows/hides, enables/disables scroll bars for all screens */
  388. /* ==========                                                                 */
  389. void FAR PASCAL ScrollBars (void)
  390.  
  391. {
  392.     static int VScroll = TRUE;
  393.     static int HScroll = TRUE;
  394.     static int Enabled = TRUE;
  395.     int     Quiescence;
  396.     SCREEN  *sp;
  397.  
  398.     if (vscrollbar) vscrollbar = TRUE;  /* normalize... */
  399.     if (hscrollbar) hscrollbar = TRUE;
  400.     Quiescence = (notquiescent == 0);
  401.  
  402.     for (sp = first_screen; sp != (SCREEN*)NULL; sp = sp->s_next_screen) {
  403.         if (vscrollbar != VScroll) {
  404.             ShowScrollBar ((HWND)sp->s_drvhandle, SB_VERT, vscrollbar);
  405.         }
  406.         if (hscrollbar != HScroll) {
  407.             ShowScrollBar ((HWND)sp->s_drvhandle, SB_HORZ, hscrollbar);
  408.         }
  409. #if !WIN30SDK
  410.         if ((Enabled != Quiescence) && Win31API && !TakingANap) {
  411.             /* note: no disabling of scroll bars during naps (i.e. fence
  412.                matching), to avoid annoying blinking */
  413.             EnableScrollBar ((HWND)sp->s_drvhandle, SB_BOTH,
  414.                              Quiescence ? ESB_ENABLE_BOTH : ESB_DISABLE_BOTH);
  415.     }
  416. #endif
  417.     }
  418.  
  419.     if ((Enabled != Quiescence) && Win31API && !TakingANap) {
  420.         Enabled = Quiescence;
  421.     }
  422.     VScroll = vscrollbar;
  423.     HScroll = hscrollbar;
  424. } /* ScrollBars */
  425.  
  426. /* updscrollbars:      updates the scroll bars for a screen */
  427. /* =============                                            */
  428. PASCAL  updscrollbars (SCREEN *sp, char w_flag)
  429.  
  430. /* the w_flag is used to determine what needs updating: if the WFHARD
  431.    bit is set, both scroll bars need an update. If the WFMOVE bit
  432.    is set, the horizontal scroll bar needs an update */
  433. /* this function assumes s_cur_window matches curwp for the first_screen */
  434. {
  435.     int ScrollMax, ScrollMin, ScrollPos;
  436.     
  437.     if (vscrollbar && (w_flag & WFHARD)) {
  438.         int    lastline;
  439.         int     topline;
  440.  
  441.         {   /*-figure-out where we are at vertically */
  442.             register LINE   *lp;
  443.             register LINE   *linep; /* header (= last) line of buffer */
  444.             LINE    *toplp;         /* top line of window */
  445.  
  446.             linep = sp->s_cur_window->w_bufp->b_linep;
  447.             toplp = sp->s_cur_window->w_linep;
  448.             topline = lastline = 0;
  449.             lp = linep;
  450.             do {
  451.                 lp = lforw(lp);
  452.                 lastline++;
  453.                 if (lp == toplp) topline = lastline;
  454.             } while (lp != linep);
  455.         }
  456.         lastline += 1 - sp->s_cur_window->w_ntrows;
  457.         if (lastline <= 1) lastline = 2;    /* to avoid scrollbar hiding */
  458.         lastline = min(lastline, MAXSCROLL);
  459.         topline = min(topline, MAXSCROLL);
  460.         GetScrollRange ((HWND)sp->s_drvhandle, SB_VERT,
  461.                         &ScrollMin, &ScrollMax);
  462.         if ((ScrollMax != lastline) || (ScrollMin != 1)) {
  463.             SetScrollRange ((HWND)sp->s_drvhandle, SB_VERT, 1,
  464.                             lastline, FALSE);
  465.             ScrollPos = -1; /* makes sure the scroll display is updated */
  466.         }
  467.         else ScrollPos = GetScrollPos ((HWND)sp->s_drvhandle, SB_VERT);
  468.         if (topline != ScrollPos) {
  469.             SetScrollPos ((HWND)sp->s_drvhandle, SB_VERT,
  470.                           topline, TRUE);
  471.         }
  472.     }
  473.     if (hscrollbar && (w_flag & (WFMOVE | WFHARD))) {
  474.         /*-figure-out where we stand horizontally */
  475.         int     row;
  476.         LINE    *lp;
  477.         WINDOW  *wp = sp->s_cur_window;
  478.         int     maxlength = 0;
  479.  
  480.         lp = wp->w_linep;
  481.         for (row = 0; (row < wp->w_ntrows) && (lp != wp->w_bufp->b_linep);
  482.              row++) {
  483.             maxlength = max(maxlength, lused(lp));
  484.             lp = lforw(lp);
  485.         }
  486.         if (maxlength <= 0) maxlength = 1;
  487.         maxlength = min(maxlength, MAXSCROLL);
  488.         row = min(wp->w_fcol, MAXSCROLL);
  489.         GetScrollRange ((HWND)sp->s_drvhandle, SB_HORZ,
  490.                         &ScrollMin, &ScrollMax);
  491.         if ((ScrollMax != maxlength) || (ScrollMin != 0)) {
  492.             SetScrollRange ((HWND)sp->s_drvhandle, SB_HORZ, 0,
  493.                             maxlength, FALSE);
  494.             ScrollPos = -1; /* makes sure the scroll display is updated */
  495.         }
  496.         else ScrollPos = GetScrollPos ((HWND)sp->s_drvhandle, SB_HORZ);
  497.         if (row != ScrollPos) {
  498.             SetScrollPos ((HWND)sp->s_drvhandle, SB_HORZ,
  499.                           row, TRUE);
  500.         }
  501.     }
  502. } /* updscrollbars */
  503.